package org.hepeng.workx.service.error;

import org.apache.commons.lang3.StringUtils;
import org.hepeng.workx.exception.ApplicationRuntimeException;

import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import java.util.Objects;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author he peng
 */
public class ErrorLoader {

    private static final String SERVICE_ERROR_FILE_PATH_KEY = "hp.java.workx.service.error";
    private static final String DEFAULT_SERVICE_ERROR_FILE_PATH = "META-INF/default-service-error.properties";
    private static final Properties SERVICE_ERROR_PROPS = new Properties();
    private static final Map<String , Error> ERROR_CACHES = new ConcurrentHashMap<>();

    static {
        String serviceErrorFilePath = System.getProperty(SERVICE_ERROR_FILE_PATH_KEY);
        if (StringUtils.isBlank(serviceErrorFilePath)) {
            serviceErrorFilePath = DEFAULT_SERVICE_ERROR_FILE_PATH;
        }
        InputStream inputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(serviceErrorFilePath);
        try {
            SERVICE_ERROR_PROPS.load(inputStream);
        } catch (IOException e) {
            throw new ApplicationRuntimeException("load " + serviceErrorFilePath + " file error" , e);
        }

    }

    private ErrorLoader() {}

    /**
     * 加载一个 Error 实例
     * @param name 配置文件中表示一个 {@link Error} 配置的名称
     * @return 返回一个 {@link Error} 实例对象
     */
    public static Error loadError(String name) {
        Error error = ERROR_CACHES.get(name);
        if (Objects.isNull(error)) {
            error = newError(SERVICE_ERROR_PROPS.getProperty(name));
            ERROR_CACHES.put(name , error);
        }
        return error;
    }

    /**
     * 创建一个新的 {@link Error} 的实例对象.
     * @param serviceError
     * @return 返回一个 {@link Error} 实例对象
     */
    private static Error newError(String serviceError) {
        if (StringUtils.isBlank(serviceError) || StringUtils.containsNone(serviceError , ",")) {
            return null;
        }

        String[] errorArr = serviceError.split(",");
        if (errorArr.length < 2) {
            return null;
        }

        return new Error() {

            private Integer code;
            private String msg;

            {
                this.code = Integer.valueOf(errorArr[0]);
                this.msg = errorArr[1];
            }
            @Override
            public Integer getCode() {
                return this.code;
            }

            @Override
            public String getMsg() {
                return this.msg;
            }

            @Override
            public String toString() {
                return "Error: Error Code [" + this.code + "] , Error Msg [" + this.msg + "]";
            }
        };
    }

}
